import KoaBody from 'koa-body'
import KoaLogger from 'koa-logger'
import * as fs from 'fs'
import * as path from 'path'
import log, { trace } from './config/logger'
import { server } from './config'
import app, { Application } from './app'

function scanApps () {
  const applicationMap = new Map<string, Application>()

  const appsBaseDir = path.join(__dirname, 'apps')
  const apps = fs.readdirSync(appsBaseDir)
  for (const a of apps) {
    const apath = path.join(appsBaseDir, a)
    if (fs.statSync(apath).isDirectory()) {
      try {
        const ar = require(apath)
        const application = ar.default || ar as Application
        application.init(app)
        applicationMap.set(a, application)
        log.info(`application ${a} load success`)
      } catch (e) {
        log.info(`application ${a} load failed`)
        log.info(e)
      }
    }
  }

  return applicationMap
}

const applicationMap = scanApps()

const port = server.port

app.use(KoaLogger({
  transporter: (str, args) => {
    trace.trace(str)
  }
}))

app.use(KoaBody())

app
  .use(async (ctx, next) => {
    try {
      await next()
    } catch (error) {
      ctx.status = error.status || 500
      const err = {
        ...error,
        code: error.status || 500
      }
      ctx.body = err
      log.info(JSON.stringify(err))
    }
  })
  .use(async (ctx, next) => {
    const url = ctx.url
    const start = 1
    const end = url.indexOf('/', start)
    let appName
    if (end === -1) {
      appName = url.substring(start, url.length)
      ctx.url = '/'
    } else {
      appName = url.substring(start, end)
      ctx.url = url.substring(end)
    }
    ctx.contextUrl = appName
    const app = applicationMap.get(appName)
    if (app && app.service instanceof Function) {
      await app.service(ctx)
    }
  })

app.listen(port, () => {
  log.info(`server running on localhost:${port}`)
})
